<!-- 图片上传组件 -->
<template>
  <div class="image-upload">
    <a-upload
      v-model:file-list="fileList"
      name="avatar"
      :max-count="1"
      list-type="picture-card"
      :class="['avatar-uploader', props.size]"
      :show-upload-list="false"
      :accept="props.accept"
      :custom-request="customRequest"
    >
      <img v-if="props.imageUrl" :src="props.imageUrl" alt="avatar" />
      <div v-else>
        <!-- <loading-outlined v-if="loading" />
        <plus-outlined v-else /> -->
        <i class="iconfont icon-add-line"></i>
        <div class="ant-upload-text font14" style="color: rgba(25, 25, 48, 0.75)">上传图片</div>
      </div>
    </a-upload>
    <div class="upload-info">
      <slot name="info"></slot>
    </div>
  </div>
</template>
<script lang="ts" setup>
  import { Form, message, UploadProps } from 'ant-design-vue'
  import { UploadRequestOption } from 'ant-design-vue/es/vc-upload/interface'
  import { axios, getBase64, getUnixFileName, isDpi } from 'g6-fn'
  import { ref } from 'vue'

  import { minioApi } from '@/services/api'
  import { http } from '@/services/http'
  import { countStrToBit } from '@/utils'

  export interface ModalProps {
    maxCount?: number
    maxFileSize?: number
    accept?: string
    action?: string
    size?: 'middle' | 'small'
    imageUrl?: string
    imageId?: string | number
    imageSize?: string | number
    dpi?: [number, number]
    imageName?: string | ''
  }
  const props = withDefaults(defineProps<ModalProps>(), {
    maxFileSize: 1,
    maxCount: 3,
    accept: 'png,jpg,jpeg',
    action: '',
    size: 'middle',
    imageUrl: '',
    imageId: '',
    imageSize: '',
    imageName: ''
  })
  const emits = defineEmits(['update:imageUrl', 'update:imageId', 'update:imageSize', 'change', 'update:imageName'])
  const formItemContext = Form.useInjectFormItemContext()

  const fileList = ref<UploadProps['fileList']>([])
  // const imageUrl = ref<string>(props.imageUrl)
  const loading = ref<boolean>(false)

  // 自定义上传
  const customRequest = async (file: UploadRequestOption<any>) => {
    // 1.将文件名称上传给服务端
    // 2.调后端接口响应参数的接口
    // 3.将图片渲染到页面上
    const fileData = file.file as any

    // 验证文件大小
    const isLt2M = fileData.size! / 1024 / 1024 < props.maxFileSize
    if (!isLt2M) {
      return message.error(`文件大小不能超过${props.maxFileSize}M`)
    }
    // 验证格式
    const postfix: string = fileData?.name?.split('.')?.slice(-1)[0]
    if (!props?.accept?.split(',')?.includes(postfix)) {
      return message.error(`仅支持${props?.accept}格式`)
    }

    // 验证分辨率
    if (props?.dpi) {
      try {
        await isDpi(file.file, props?.dpi)
      } catch (error) {
        return message.error(`仅支持${props?.dpi[0]}*${props?.dpi[1]}分辨率的图片`)
      }
    }
    // 检查文件名长度是否超过200个字节
    // if (fileData.name.length > 200) {
    if (countStrToBit(fileData.name) > 200) {
      message.error('图片名不能超过200个字节')
      return
    }

    loading.value = true
    try {
      const fileName = '/spa' + getUnixFileName(fileData.name)
      console.log('fileName', fileName)
      console.log('fileData.name', fileData.name)

      const res = await minioApi.upload(fileName)
      if (res?.code === 'SYSTEM-100000') {
        const CancelToken = axios.CancelToken
        const source = CancelToken.source()
        const config = {
          timeout: 120000, //设置超时时长
          cancelToken: source.token
        }
        await http.upload(res.data, fileData, config)
        emits('update:imageName', fileName)
        getBase64(fileData, (base64Url: string) => {
          // imageUrl.value = base64Url
          loading.value = false
          fileList.value![0] = {
            uid: fileName,
            name: fileName,
            status: 'done',
            url: base64Url,
            size: fileData.size
          }
          emits('update:imageUrl', base64Url)
          emits('update:imageId', fileName)
          emits('update:imageSize', fileData.size)
          emits('change', fileName)
          formItemContext.onFieldChange()
        })
      } else {
        message.error('上传失败')
        loading.value = false
        emits('update:imageUrl', undefined)
        emits('update:imageId', undefined)
      }
    } catch (error) {
      message.error('接口错误，上传失败')
      loading.value = false
    }
  }
</script>
<style lang="less" scoped>
  .middle {
    :deep(.ant-upload.ant-upload-select-picture-card) {
      margin: 0;
      width: 140px;
      height: 140px;
      background-color: #fff;
    }
  }

  .small {
    :deep(.ant-upload.ant-upload-select-picture-card) {
      margin: 0;
      width: 90px;
      height: 90px;
      background-color: #fff;
    }
  }

  .image-upload {
    display: flex;
    // justify-content: space-between;

    .avatar-uploader {
      img {
        width: 100%;
        height: 100%;
        object-fit: contain;
      }
    }

    .upload-info {
      display: flex;
      align-items: flex-end;
      margin-left: 24px;
      word-break: break-all;
      // flex: 1;
    }

    .ant-upload-text {
      margin-top: 8px;
    }
  }
</style>
